package com.qfedu.filters;

import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.qfedu.entity.ResultStatus;
import com.qfedu.entity.ResultVo;
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * 作者：刘随阳
 * 时间: 2021/9/8 19:47
 * 描述：神光照耀,太白成瑞。六丙来迎,百福悠归
 */
@Component
public class GlobalAuthFilter implements GlobalFilter, Ordered {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //针对所有的路由进行过滤
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //放行me-user，index，product
        String uri = exchange.getRequest().getPath().toString();
        if (Pattern.matches("/user/(.*)",uri)
                || Pattern.matches("/sms/(.*)",uri)
                || Pattern.matches("/index/(.*)",uri)
                || Pattern.matches("/product/(.*)",uri)
                || Pattern.matches("/wx/(.*)",uri)
                || Pattern.matches("/cf/(.*)",uri) ){
           return chain.filter(exchange);
        }

        //过滤器的前处理
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String token = request.getHeaders().getFirst("token");
        if(StringUtils.isEmpty(token)){
            return response(response,ResultVo.loginStatus(ResultStatus.NO_LOGIN,"没有登录"));
        }else{
            if(token == null){
                ResultVo noLogin = ResultVo.loginStatus(ResultStatus.NO_LOGIN,"用户未登录");
                return response(response,noLogin);
            }

            //检查令牌在redis缓存中是否命中
            if (!stringRedisTemplate.hasKey(token)){
                ResultVo overdue = ResultVo.loginStatus(ResultStatus.OUT_DUE,"登录过期,请重新登录!");
                return response(response,overdue);
            }else{
                try {
                    Long expire = stringRedisTemplate.boundSetOps(token).getExpire();       //打印当前令牌剩余时间
                    System.out.println("剩余时间:"+expire);
                    String s = stringRedisTemplate.opsForValue().get(token);                //取出value
                    System.out.println("value:"+s);
                    JwtParser parser = Jwts.parser();                                       //jwt令牌解析
                    parser.setSigningKey("123456");
                    Jws<Claims> claimsJws = parser.parseClaimsJws(token);
                    stringRedisTemplate.expire(token,30, TimeUnit.MINUTES);          //重置令牌缓存过期时间
                    Long expire1 = stringRedisTemplate.boundSetOps(token).getExpire();      //打印重置缓存过期时间后，令牌的剩余时间
                    System.out.println("剩余时间:"+expire1);
                }catch (ExpiredJwtException e){
                    ResultVo overdue = ResultVo.loginStatus(ResultStatus.OUT_DUE,"登录过期,请重新登录!");
                    return response(response,overdue);
                }catch (UnsupportedJwtException e){
                    ResultVo overdue = ResultVo.loginStatus(ResultStatus.ILLEGAL,"令牌不合法!");
                    return response(response,overdue);
                }catch (Exception e){
                    ResultVo overdue = ResultVo.loginStatus(ResultStatus.NO_LOGIN,"请先登录!");
                    return response(response,overdue);
                }
                return  chain.filter(exchange);  //放行
            }
        }



    }

    private Mono<Void>  response(ServerHttpResponse response,Object msg){
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        String resJson = JSONUtil.toJsonPrettyStr(msg);
        DataBuffer dataBuffer = response.bufferFactory().wrap(resJson.getBytes());
        return response.writeWith(Flux.just(dataBuffer));//响应json数据
    }




    //数字越小越先执行
    @Override
    public int getOrder() {
        return 0;
    }
}